package com.lds.config.center.server.client.scheduled;

import com.fasterxml.jackson.core.type.TypeReference;
import com.lds.config.center.client.common.model.response.NotifyUpdateItemResponse;
import com.lds.config.center.server.business.itemchangerelease.mapper.ItemChangeReleaseMapper;
import com.lds.config.center.common.model.itemchangerelease.request.ItemChangeReleaseBaseListPageRequest;
import com.lds.config.center.common.model.itemchangerelease.response.ItemChangeReleaseBaseResponse;
import com.lds.config.center.server.business.itemchangerelease.service.ItemChangeReleaseBaseService;
import com.lds.config.center.server.business.namespace.service.NamespaceBaseService;
import com.lds.config.center.server.client.service.ClientService;
import com.lds.config.center.server.common.model.NamespaceName;
import com.lds.management.center.common.model.db.PageResult;
import com.lds.management.center.common.model.dto.ResultDTO;
import com.lds.management.center.common.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class ReleaseScheduler extends AbstractInstanceScheduler<ItemChangeReleaseBaseResponse> {
    private final ItemChangeReleaseBaseService itemChangeReleaseBaseService;
    private final ItemChangeReleaseMapper itemChangeReleaseMapper;
    private final ClientService clientService;
    private final NamespaceBaseService namespaceBaseService;

    @Override
    protected ResultDTO<PageResult<ItemChangeReleaseBaseResponse>> pageInstances() {
        ItemChangeReleaseBaseListPageRequest request = new ItemChangeReleaseBaseListPageRequest();
        request.setGtId(getId());
        request.setPageNum(1);
        request.setPageSize(500);
        request.setOrderByKey("id");
        request.setOrderByDesc(false);
        return itemChangeReleaseBaseService.listItemChangeReleasePage(request);
    }

    @Override
    protected Long id(ItemChangeReleaseBaseResponse instance) {
        return instance.getId();
    }

    @Override
    protected void handleInstances(List<ItemChangeReleaseBaseResponse> instances) {
        Map<Long, List<ItemChangeReleaseBaseResponse>> namespaceIdMap = instances.stream().collect(Collectors.groupingBy(ItemChangeReleaseBaseResponse::getNamespaceId));
        namespaceIdMap.forEach((namespaceId, list) -> clientService.autoNotify(buildNotifyUpdateItemResponse(namespaceId, list)));

        itemChangeReleaseMapper.deleteBatchIds(instances.stream().map(ItemChangeReleaseBaseResponse::getId).collect(Collectors.toList()));
    }

    private NotifyUpdateItemResponse buildNotifyUpdateItemResponse(Long namespaceId, List<ItemChangeReleaseBaseResponse> list) {
        NamespaceName namespaceName = getNamespaceName(namespaceId);
        return NotifyUpdateItemResponse.builder()
                .envId(namespaceId)
                .envName(namespaceName.getEnvName())
                .clusterId(namespaceName.getClusterId())
                .clusterName(namespaceName.getClusterName())
                .appId(namespaceName.getAppId())
                .appName(namespaceName.getAppName())
                .namespaceId(namespaceId)
                .namespaceName(namespaceName.getNamespaceName())
                .itemMap(itemMap(list))
                .build();
    }

    private NamespaceName getNamespaceName(Long namespaceId) {
        return namespaceBaseService.getNamespaceName(namespaceId);
    }

    private Map<String, String> itemMap(List<ItemChangeReleaseBaseResponse> list) {
        Map<String, String> itemMap = new HashMap<>();
        if (CollectionUtils.isEmpty(list)) return null;
        list.forEach(item -> {
            String messages = item.getMessages();
            Map<String, String> map = JsonUtil.fromJson(messages, new TypeReference<Map<String, String>>() {});
            if (MapUtils.isNotEmpty(map)) {
                itemMap.putAll(map);
            }
        });
        return itemMap;
    }

}
